* make xmlgeneric a class.
* encapsulate more of xmlgeneric
* use scoped enum
* encapsulate a bit more.
* retire xg_string type
* use scoped enums
* rule of zero applied to xmlgeneric class.
* remove test code
#include <type_traits> // for add_const<>::type
#include "defs.h" // for Waypoint, route_head, computed_trkdata, waypt_add, route_disp, track_disp_all, case_ignore_strncmp, track_add_head, track_add_wpt, track_recompute, xml_parse_time, CSTR, wp_flags, WAYPT_SET, unknown_alt
-#include "xmlgeneric.h" // for xg_string, build_xg_tag_map, xml_deinit, xml_init, xml_read
+#include "xmlgeneric.h" // for xml_deinit, xml_init, xml_read
#define MYNAME "gtc"
void
GtrnctrFormat::rd_init(const QString& fname)
{
- xml_init(fname, build_xg_tag_map(this, gtc_map), nullptr, gtc_tags_to_ignore, nullptr, true);
+ xml_reader = new XmlGenericReader;
+ xml_reader->xml_init(fname, this, gtc_map, nullptr, gtc_tags_to_ignore, nullptr);
}
void
GtrnctrFormat::read()
{
- xml_read();
+ xml_reader->xml_read();
}
void
GtrnctrFormat::rd_deinit()
{
- xml_deinit();
+ delete xml_reader;
+ xml_reader = nullptr;
}
void
}
void
-GtrnctrFormat::gtc_trk_s(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_s(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
trk_head = new route_head;
track_add_head(trk_head);
}
void
-GtrnctrFormat::gtc_trk_ident(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_ident(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
trk_head->rte_name = args;
}
void
-GtrnctrFormat::gtc_trk_lap_s(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_lap_s(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
lap_ct++;
lap_s = 1;
}
void
-GtrnctrFormat::gtc_trk_lap_e(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_lap_e(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
lap_s = 0;
}
void
-GtrnctrFormat::gtc_trk_pnt_s(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_pnt_s(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp = new Waypoint;
}
void
-GtrnctrFormat::gtc_trk_pnt_e(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_pnt_e(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
if (wpt_tmp->longitude != 0. && wpt_tmp->latitude != 0.) {
if (lap_s) {
}
void
-GtrnctrFormat::gtc_trk_utc(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_utc(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->creation_time = xml_parse_time(args);
}
void
-GtrnctrFormat::gtc_trk_lat(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_lat(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->latitude = args.toDouble();
}
void
-GtrnctrFormat::gtc_trk_long(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_long(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->longitude = args.toDouble();
}
void
-GtrnctrFormat::gtc_trk_alt(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_alt(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->altitude = args.toDouble();
}
}
void
-GtrnctrFormat::gtc_trk_pwr(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_pwr(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->power = args.toDouble();
}
void
-GtrnctrFormat::gtc_trk_spd(xg_string args, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_trk_spd(const QString& args, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp->set_speed(args.toDouble());
}
}
void
-GtrnctrFormat::gtc_wpt_crs_e(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_wpt_crs_e(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
if (wpt_tmp->longitude != 0. && wpt_tmp->latitude != 0.) {
waypt_add(wpt_tmp);
}
void
-GtrnctrFormat::gtc_wpt_pnt_s(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_wpt_pnt_s(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
wpt_tmp = new Waypoint;
lap_ct++;
}
void
-GtrnctrFormat::gtc_wpt_pnt_e(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+GtrnctrFormat::gtc_wpt_pnt_e(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
if (wpt_tmp->longitude != 0. && wpt_tmp->latitude != 0.) {
/* Add the begin position of a CourseLap as
#include "format.h" // for Format
#include "gbfile.h" // for gbfile
#include "src/core/datetime.h" // for DateTime
-#include "xmlgeneric.h" // for cb_cdata, xg_functor_map_entry, xg_string, cb_start, cb_end
+#include "xmlgeneric.h" // for cb_cdata, xg_functor_map_entry, cb_start, cb_end
class GtrnctrFormat : public Format
void gtc_crs_hdr(const route_head* rte);
void gtc_crs_ftr(const route_head* /* unused */);
- void gtc_trk_s(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_ident(xg_string args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_lap_s(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_lap_e(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_pnt_s(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_pnt_e(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_utc(xg_string args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_lat(xg_string args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_long(xg_string args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_alt(xg_string args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_s(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_ident(const QString& args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_lap_s(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_lap_e(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_pnt_s(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_pnt_e(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_utc(const QString& args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_lat(const QString& args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_long(const QString& args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_alt(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_trk_dist(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_trk_hr(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_trk_cad(const QString& args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_pwr(xg_string args, const QXmlStreamAttributes* /* unused */);
- void gtc_trk_spd(xg_string args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_pwr(const QString& args, const QXmlStreamAttributes* /* unused */);
+ void gtc_trk_spd(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_wpt_crs_s(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_wpt_crs_e(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_wpt_pnt_s(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void gtc_wpt_pnt_e(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_wpt_crs_e(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_wpt_pnt_s(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void gtc_wpt_pnt_e(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
void gtc_wpt_ident(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_wpt_lat(const QString& args, const QXmlStreamAttributes* /* unused */);
void gtc_wpt_long(const QString& args, const QXmlStreamAttributes* /* unused */);
},
};
- QList<xg_functor_map_entry<GtrnctrFormat>> gtc_map = {
+ QList<XmlGenericReader::xg_fmt_map_entry<GtrnctrFormat>> gtc_map = {
/* courses tcx v1 & v2 */
- { &GtrnctrFormat::gtc_trk_s, cb_start, "/Courses/Course" },
- { &GtrnctrFormat::gtc_trk_ident,cb_cdata, "/Courses/Course/Name"},
- { &GtrnctrFormat::gtc_trk_pnt_s,cb_start, "/Courses/Course/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_pnt_e,cb_end, "/Courses/Course/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_utc, cb_cdata, "/Courses/Course/Track/Trackpoint/Time" },
- { &GtrnctrFormat::gtc_trk_lat, cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LatitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_long, cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LongitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_alt, cb_cdata, "/Courses/Course/Track/Trackpoint/AltitudeMeters" },
- { &GtrnctrFormat::gtc_trk_hr, cb_cdata, "/Courses/Course/Track/Trackpoint/HeartRateBpm" },
- { &GtrnctrFormat::gtc_trk_cad, cb_cdata, "/Courses/Course/Track/Trackpoint/Cadence" },
- { &GtrnctrFormat::gtc_wpt_crs_s,cb_start, "/Courses/Course/CoursePoint" },
- { &GtrnctrFormat::gtc_wpt_crs_e,cb_end, "/Courses/Course/CoursePoint" },
- { &GtrnctrFormat::gtc_wpt_ident,cb_cdata, "/Courses/Course/CoursePoint/Name"},
- { &GtrnctrFormat::gtc_trk_utc, cb_cdata, "/Courses/Course/CoursePoint/Time"},
- { &GtrnctrFormat::gtc_wpt_lat, cb_cdata, "/Courses/Course/CoursePoint/Position/LatitudeDegrees"},
- { &GtrnctrFormat::gtc_wpt_long, cb_cdata, "/Courses/Course/CoursePoint/Position/LongitudeDegrees"},
- { &GtrnctrFormat::gtc_trk_alt, cb_cdata, "/Courses/Course/CoursePoint/AltitudeMeters" },
- { &GtrnctrFormat::gtc_wpt_icon, cb_cdata, "/Courses/Course/CoursePoint/PointType" },
- { &GtrnctrFormat::gtc_wpt_notes,cb_cdata, "/Courses/Course/CoursePoint/Notes" },
+ { &GtrnctrFormat::gtc_trk_s, xg_cb_type::cb_start, "/Courses/Course" },
+ { &GtrnctrFormat::gtc_trk_ident, xg_cb_type::cb_cdata, "/Courses/Course/Name"},
+ { &GtrnctrFormat::gtc_trk_pnt_s, xg_cb_type::cb_start, "/Courses/Course/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_pnt_e, xg_cb_type::cb_end, "/Courses/Course/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_utc, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/Time" },
+ { &GtrnctrFormat::gtc_trk_lat, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LatitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_long, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/Position/LongitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_alt, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/AltitudeMeters" },
+ { &GtrnctrFormat::gtc_trk_hr, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/HeartRateBpm" },
+ { &GtrnctrFormat::gtc_trk_cad, xg_cb_type::cb_cdata, "/Courses/Course/Track/Trackpoint/Cadence" },
+ { &GtrnctrFormat::gtc_wpt_crs_s, xg_cb_type::cb_start, "/Courses/Course/CoursePoint" },
+ { &GtrnctrFormat::gtc_wpt_crs_e, xg_cb_type::cb_end, "/Courses/Course/CoursePoint" },
+ { &GtrnctrFormat::gtc_wpt_ident, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/Name"},
+ { &GtrnctrFormat::gtc_trk_utc, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/Time"},
+ { &GtrnctrFormat::gtc_wpt_lat, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/Position/LatitudeDegrees"},
+ { &GtrnctrFormat::gtc_wpt_long, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/Position/LongitudeDegrees"},
+ { &GtrnctrFormat::gtc_trk_alt, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/AltitudeMeters" },
+ { &GtrnctrFormat::gtc_wpt_icon, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/PointType" },
+ { &GtrnctrFormat::gtc_wpt_notes, xg_cb_type::cb_cdata, "/Courses/Course/CoursePoint/Notes" },
/* history tcx v2 (activities) */
- { &GtrnctrFormat::gtc_trk_s, cb_start, "/Activities/Activity" },
- { &GtrnctrFormat::gtc_trk_ident,cb_cdata, "/Activities/Activity/Id" },
- { &GtrnctrFormat::gtc_trk_lap_s,cb_start, "/Activities/Activity/Lap" },
- { &GtrnctrFormat::gtc_trk_lap_e,cb_end, "/Activities/Activity/Lap" },
- { &GtrnctrFormat::gtc_trk_pnt_s,cb_start, "/Activities/Activity/Lap/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_pnt_e,cb_end, "/Activities/Activity/Lap/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_utc, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Time" },
- { &GtrnctrFormat::gtc_trk_lat, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Position/LatitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_long, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Position/LongitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_alt, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/AltitudeMeters" },
- { &GtrnctrFormat::gtc_trk_dist, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/DistanceMeters" },
- { &GtrnctrFormat::gtc_trk_hr, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/HeartRateBpm" },
- { &GtrnctrFormat::gtc_trk_cad, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Cadence" },
- { &GtrnctrFormat::gtc_trk_pwr, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/ns3:TPX/ns3:Watts" },
+ { &GtrnctrFormat::gtc_trk_s, xg_cb_type::cb_start, "/Activities/Activity" },
+ { &GtrnctrFormat::gtc_trk_ident, xg_cb_type::cb_cdata, "/Activities/Activity/Id" },
+ { &GtrnctrFormat::gtc_trk_lap_s, xg_cb_type::cb_start, "/Activities/Activity/Lap" },
+ { &GtrnctrFormat::gtc_trk_lap_e, xg_cb_type::cb_end, "/Activities/Activity/Lap" },
+ { &GtrnctrFormat::gtc_trk_pnt_s, xg_cb_type::cb_start, "/Activities/Activity/Lap/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_pnt_e, xg_cb_type::cb_end, "/Activities/Activity/Lap/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_utc, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Time" },
+ { &GtrnctrFormat::gtc_trk_lat, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Position/LatitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_long, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Position/LongitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_alt, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/AltitudeMeters" },
+ { &GtrnctrFormat::gtc_trk_dist, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/DistanceMeters" },
+ { &GtrnctrFormat::gtc_trk_hr, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/HeartRateBpm" },
+ { &GtrnctrFormat::gtc_trk_cad, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Cadence" },
+ { &GtrnctrFormat::gtc_trk_pwr, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/ns3:TPX/ns3:Watts" },
// Sample from Marcelo Kittlein 5/2014 declares a default namespace with the start tag of the TPX element,
// and thus doesn't use prefixes.
- { &GtrnctrFormat::gtc_trk_pwr, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/TPX/Watts" },
+ { &GtrnctrFormat::gtc_trk_pwr, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/TPX/Watts" },
// It looks like Speed and Watts should be siblings, but Garmin can't get
// their namespace act very consistent. This works for a sample provided
// by Laurent Desmons in 5/2013.
- { &GtrnctrFormat::gtc_trk_spd, cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/TPX/Speed" },
+ { &GtrnctrFormat::gtc_trk_spd, xg_cb_type::cb_cdata, "/Activities/Activity/Lap/Track/Trackpoint/Extensions/TPX/Speed" },
/* history tcx v1 */
- { &GtrnctrFormat::gtc_trk_s, cb_start, "/History/Run" },
- { &GtrnctrFormat::gtc_trk_ident,cb_cdata, "/History/Run/Id" },
- { &GtrnctrFormat::gtc_trk_lap_s,cb_start, "/History/Run/Lap" },
- { &GtrnctrFormat::gtc_trk_lap_e,cb_end, "/History/Run/Lap" },
- { &GtrnctrFormat::gtc_trk_pnt_s,cb_start, "/History/Run/Lap/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_pnt_e,cb_end, "/History/Run/Lap/Track/Trackpoint" },
- { &GtrnctrFormat::gtc_trk_utc, cb_cdata, "/History/Run/Lap/Track/Trackpoint/Time" },
- { &GtrnctrFormat::gtc_trk_lat, cb_cdata, "/History/Run/Lap/Track/Trackpoint/Position/LatitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_long, cb_cdata, "/History/Run/Lap/Track/Trackpoint/Position/LongitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_alt, cb_cdata, "/History/Run/Lap/Track/Trackpoint/AltitudeMeters" },
- { &GtrnctrFormat::gtc_trk_hr, cb_cdata, "/History/Run/Lap/Track/Trackpoint/HeartRateBpm" },
- { &GtrnctrFormat::gtc_trk_cad, cb_cdata, "/History/Run/Lap/Track/Trackpoint/Cadence" },
-
- { &GtrnctrFormat::gtc_wpt_pnt_s,cb_start, "/Courses/Course/Lap/BeginPosition" },
- { &GtrnctrFormat::gtc_wpt_pnt_e,cb_end, "/Courses/Course/Lap/BeginPosition" },
- { &GtrnctrFormat::gtc_wpt_lat, cb_cdata, "/Courses/Course/Lap/BeginPosition/LatitudeDegrees" },
- { &GtrnctrFormat::gtc_wpt_long, cb_cdata, "/Courses/Course/Lap/BeginPosition/LongitudeDegrees" },
- { &GtrnctrFormat::gtc_trk_alt, cb_cdata, "/Courses/Course/Lap/BeginAltitudeMeters" }
+ { &GtrnctrFormat::gtc_trk_s, xg_cb_type::cb_start, "/History/Run" },
+ { &GtrnctrFormat::gtc_trk_ident, xg_cb_type::cb_cdata, "/History/Run/Id" },
+ { &GtrnctrFormat::gtc_trk_lap_s, xg_cb_type::cb_start, "/History/Run/Lap" },
+ { &GtrnctrFormat::gtc_trk_lap_e, xg_cb_type::cb_end, "/History/Run/Lap" },
+ { &GtrnctrFormat::gtc_trk_pnt_s, xg_cb_type::cb_start, "/History/Run/Lap/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_pnt_e, xg_cb_type::cb_end, "/History/Run/Lap/Track/Trackpoint" },
+ { &GtrnctrFormat::gtc_trk_utc, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/Time" },
+ { &GtrnctrFormat::gtc_trk_lat, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/Position/LatitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_long, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/Position/LongitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_alt, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/AltitudeMeters" },
+ { &GtrnctrFormat::gtc_trk_hr, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/HeartRateBpm" },
+ { &GtrnctrFormat::gtc_trk_cad, xg_cb_type::cb_cdata, "/History/Run/Lap/Track/Trackpoint/Cadence" },
+
+ { &GtrnctrFormat::gtc_wpt_pnt_s, xg_cb_type::cb_start, "/Courses/Course/Lap/BeginPosition" },
+ { &GtrnctrFormat::gtc_wpt_pnt_e, xg_cb_type::cb_end, "/Courses/Course/Lap/BeginPosition" },
+ { &GtrnctrFormat::gtc_wpt_lat, xg_cb_type::cb_cdata, "/Courses/Course/Lap/BeginPosition/LatitudeDegrees" },
+ { &GtrnctrFormat::gtc_wpt_long, xg_cb_type::cb_cdata, "/Courses/Course/Lap/BeginPosition/LongitudeDegrees" },
+ { &GtrnctrFormat::gtc_trk_alt, xg_cb_type::cb_cdata, "/Courses/Course/Lap/BeginAltitudeMeters" }
};
+ XmlGenericReader* xml_reader{nullptr};
int gtc_indent_level{};
};
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "src/core/xmltag.h" // for xml_findfirst, xml_tag, fs_xml, xml_attribute, xml_findnext
#include "units.h" // for UnitsFormatter, UnitsFormatter...
-#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
+#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
// Icons provided and hosted by Google. Used with permission.
kml_color_sequencer.seq += kml_color_sequencer.step;
}
-void KmlFormat::wpt_s(xg_string /*args*/, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_s(const QString& /*args*/, const QXmlStreamAttributes* /*attrs*/)
{
if (wpt_tmp) {
fatal(MYNAME ": wpt_s: invalid kml file\n");
wpt_timespan_end = gpsbabel::DateTime();
}
-void KmlFormat::wpt_e(xg_string /*args*/, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_e(const QString& /*args*/, const QXmlStreamAttributes* /*attrs*/)
{
if (!wpt_tmp) {
fatal(MYNAME ": wpt_e: invalid kml file\n");
wpt_tmp_queued = false;
}
-void KmlFormat::wpt_name(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_name(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
if (!wpt_tmp) {
fatal(MYNAME ": wpt_name: invalid kml file\n");
wpt_tmp->description += args.trimmed();
}
-void KmlFormat::wpt_time(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_time(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
if (!wpt_tmp) {
fatal(MYNAME ": wpt_time: invalid kml file\n");
wpt_tmp->SetCreationTime(xml_parse_time(args));
}
-void KmlFormat::wpt_ts_begin(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_ts_begin(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
wpt_timespan_begin = xml_parse_time(args);
}
-void KmlFormat::wpt_ts_end(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_ts_end(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
wpt_timespan_end = xml_parse_time(args);
}
wpt_tmp_queued = true;
}
-void KmlFormat::wpt_icon(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::wpt_icon(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
if (wpt_tmp) {
wpt_tmp->icon_descr = args;
}
}
-void KmlFormat::trk_coord(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::trk_coord(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
auto* trk_head = new route_head;
if (wpt_tmp && !wpt_tmp->shortname.isEmpty()) {
}
}
-void KmlFormat::gx_trk_s(xg_string /*args*/, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::gx_trk_s(const QString& /*args*/, const QXmlStreamAttributes* /*attrs*/)
{
gx_trk_head = new route_head;
if (wpt_tmp && !wpt_tmp->shortname.isEmpty()) {
gx_trk_coords = new QList<std::tuple<int, double, double, double>>;
}
-void KmlFormat::gx_trk_e(xg_string /*args*/, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::gx_trk_e(const QString& /*args*/, const QXmlStreamAttributes* /*attrs*/)
{
// Check that for every temporal value (kml:when) in a kml:Track there is a position (kml:coord) value.
// Check that for every temporal value (kml:when) in a gx:Track there is a position (gx:coord) value.
gx_trk_coords = nullptr;
}
-void KmlFormat::gx_trk_when(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::gx_trk_when(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
if (! gx_trk_times) {
fatal(MYNAME ": gx_trk_when: invalid kml file\n");
gx_trk_times->append(xml_parse_time(args));
}
-void KmlFormat::gx_trk_coord(xg_string args, const QXmlStreamAttributes* /*attrs*/)
+void KmlFormat::gx_trk_coord(const QString& args, const QXmlStreamAttributes* /*attrs*/)
{
if (! gx_trk_coords) {
fatal(MYNAME ": gx_trk_coord: invalid kml file\n");
void KmlFormat::rd_init(const QString& fname)
{
- xml_init(fname, build_xg_tag_map(this, kml_map), nullptr, kml_tags_to_ignore, kml_tags_to_skip, true);
+ xml_reader = new XmlGenericReader;
+ xml_reader->xml_init(fname, this, kml_map, nullptr, kml_tags_to_ignore, kml_tags_to_skip);
}
void KmlFormat::read()
{
- xml_read();
+ xml_reader->xml_read();
}
void KmlFormat::rd_deinit()
{
- xml_deinit();
+ delete xml_reader;
+ xml_reader = nullptr;
}
void KmlFormat::wr_init(const QString& fname)
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
#include "units.h" // for UnitsFormatter
-#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_string, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
+#include "xmlgeneric.h" // for cb_cdata, cb_end, cb_start, xg_callback, xg_cb_type, xml_deinit, xml_ignore_tags, xml_init, xml_read, xg_tag_mapping
class KmlFormat : public Format
gb_color color;
} kml_color_sequencer;
- QList<xg_functor_map_entry<KmlFormat>> kml_map = {
- {&KmlFormat::wpt_s, cb_start, "/Placemark"},
- {&KmlFormat::wpt_e, cb_end, "/Placemark"},
- {&KmlFormat::wpt_name, cb_cdata, "/Placemark/name"},
- {&KmlFormat::wpt_desc, cb_cdata, "/Placemark/description"},
- {&KmlFormat::wpt_ts_begin, cb_cdata,"/Placemark/TimeSpan/begin"},
- {&KmlFormat::wpt_ts_end, cb_cdata, "/Placemark/TimeSpan/end"},
- {&KmlFormat::wpt_time, cb_cdata, "/Placemark/TimeStamp/when"},
+ QList<XmlGenericReader::xg_fmt_map_entry<KmlFormat>> kml_map = {
+ {&KmlFormat::wpt_s, xg_cb_type::cb_start, "/Placemark"},
+ {&KmlFormat::wpt_e, xg_cb_type::cb_end, "/Placemark"},
+ {&KmlFormat::wpt_name, xg_cb_type::cb_cdata, "/Placemark/name"},
+ {&KmlFormat::wpt_desc, xg_cb_type::cb_cdata, "/Placemark/description"},
+ {&KmlFormat::wpt_ts_begin, xg_cb_type::cb_cdata,"/Placemark/TimeSpan/begin"},
+ {&KmlFormat::wpt_ts_end, xg_cb_type::cb_cdata, "/Placemark/TimeSpan/end"},
+ {&KmlFormat::wpt_time, xg_cb_type::cb_cdata, "/Placemark/TimeStamp/when"},
// Alias for above used in KML 2.0
- {&KmlFormat::wpt_time, cb_cdata, "/Placemark/TimeInstant/timePosition"},
- {&KmlFormat::wpt_coord, cb_cdata, "/Placemark/(.+/)?Point/coordinates"},
- {&KmlFormat::wpt_icon, cb_cdata, "/Placemark/Style/Icon/href"},
- {&KmlFormat::trk_coord, cb_cdata, "/Placemark/(.+/)?LineString/coordinates"},
- {&KmlFormat::trk_coord, cb_cdata, "/Placemark/(.+)/?LinearRing/coordinates"},
- {&KmlFormat::gx_trk_s, cb_start, "/Placemark/(.+/)?gx:Track"},
- {&KmlFormat::gx_trk_e, cb_end, "/Placemark/(.+/)?gx:Track"},
- {&KmlFormat::gx_trk_when, cb_cdata, "/Placemark/(.+/)?gx:Track/when"},
- {&KmlFormat::gx_trk_coord, cb_cdata, "/Placemark/(.+/)?gx:Track/gx:coord"},
- {&KmlFormat::gx_trk_s, cb_start, "/Placemark/(.+/)?Track"}, // KML 2.3
- {&KmlFormat::gx_trk_e, cb_end, "/Placemark/(.+/)?Track"}, // KML 2.3
- {&KmlFormat::gx_trk_when, cb_cdata, "/Placemark/(.+/)?Track/when"}, // KML 2.3
- {&KmlFormat::gx_trk_coord, cb_cdata, "/Placemark/(.+/)?Track/coord"}, // KML 2.3
+ {&KmlFormat::wpt_time, xg_cb_type::cb_cdata, "/Placemark/TimeInstant/timePosition"},
+ {&KmlFormat::wpt_coord, xg_cb_type::cb_cdata, "/Placemark/(.+/)?Point/coordinates"},
+ {&KmlFormat::wpt_icon, xg_cb_type::cb_cdata, "/Placemark/Style/Icon/href"},
+ {&KmlFormat::trk_coord, xg_cb_type::cb_cdata, "/Placemark/(.+/)?LineString/coordinates"},
+ {&KmlFormat::trk_coord, xg_cb_type::cb_cdata, "/Placemark/(.+)/?LinearRing/coordinates"},
+ {&KmlFormat::gx_trk_s, xg_cb_type::cb_start, "/Placemark/(.+/)?gx:Track"},
+ {&KmlFormat::gx_trk_e, xg_cb_type::cb_end, "/Placemark/(.+/)?gx:Track"},
+ {&KmlFormat::gx_trk_when, xg_cb_type::cb_cdata, "/Placemark/(.+/)?gx:Track/when"},
+ {&KmlFormat::gx_trk_coord, xg_cb_type::cb_cdata, "/Placemark/(.+/)?gx:Track/gx:coord"},
+ {&KmlFormat::gx_trk_s, xg_cb_type::cb_start, "/Placemark/(.+/)?Track"}, // KML 2.3
+ {&KmlFormat::gx_trk_e, xg_cb_type::cb_end, "/Placemark/(.+/)?Track"}, // KML 2.3
+ {&KmlFormat::gx_trk_when, xg_cb_type::cb_cdata, "/Placemark/(.+/)?Track/when"}, // KML 2.3
+ {&KmlFormat::gx_trk_coord, xg_cb_type::cb_cdata, "/Placemark/(.+/)?Track/coord"}, // KML 2.3
};
+ XmlGenericReader* xml_reader{nullptr};
// The TimeSpan/begin and TimeSpan/end DateTimes:
gpsbabel::DateTime wpt_timespan_begin, wpt_timespan_end;
#include "osm.h"
#include "src/core/datetime.h" // for DateTime
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
-#include "xmlgeneric.h" // for xg_string, build_xg_tag_map, xml_deinit, xml_init, xml_read
+#include "xmlgeneric.h" // for xml_deinit, xml_init, xml_read
#define MYNAME "osm"
}
void
-OsmFormat::osm_node_end(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+OsmFormat::osm_node_end(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
if (wpt) {
if (wpt->wpt_flags.fmt_use) {
}
void
-OsmFormat::osm_node(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_node(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
wpt = new Waypoint;
}
void
-OsmFormat::osm_node_tag(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_node_tag(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
QString key, value;
signed char ikey;
}
void
-OsmFormat::osm_way(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_way(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
rte = new route_head;
// create a wpt to represent the route center if it has a center tag
}
void
-OsmFormat::osm_way_nd(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_way_nd(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
if (attrv->hasAttribute("ref")) {
QString atstr = attrv->value("ref").toString();
}
void
-OsmFormat::osm_way_tag(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_way_tag(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
QString key, value;
signed char ikey;
}
void
-OsmFormat::osm_way_center(xg_string /*unused*/, const QXmlStreamAttributes* attrv)
+OsmFormat::osm_way_center(const QString& /*unused*/, const QXmlStreamAttributes* attrv)
{
wpt->wpt_flags.fmt_use = 1;
}
void
-OsmFormat::osm_way_end(xg_string /*unused*/, const QXmlStreamAttributes* /*unused*/)
+OsmFormat::osm_way_end(const QString& /*unused*/, const QXmlStreamAttributes* /*unused*/)
{
if (rte) {
route_add_head(rte);
osm_features_init();
}
- xml_init(fname, build_xg_tag_map(this, osm_map), nullptr, nullptr, nullptr, true);
+ xml_reader = new XmlGenericReader;
+ xml_reader->xml_init(fname, this, osm_map);
}
void
OsmFormat::read()
{
- xml_read();
+ xml_reader->xml_read();
}
void
OsmFormat::rd_deinit()
{
- xml_deinit();
+ delete xml_reader;
+ xml_reader = nullptr;
+
waypoints.clear();
}
#include "format.h" // for Format
#include "src/core/file.h" // for File
#include "src/core/xmlstreamwriter.h" // for XmlStreamWriter
-#include "xmlgeneric.h" // for xg_functor_map_entry, cb_start, cb_end, xg_string
+#include "xmlgeneric.h" // for xg_functor_map_entry, cb_start, cb_end
class OsmFormat : public Format
char osm_feature_ikey(const QString& key) const;
QString osm_feature_symbol(int ikey, const char* value) const;
static QString osm_strip_html(const QString& str);
- void osm_node_end(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
- void osm_node(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_node_tag(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_way(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_way_nd(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_way_tag(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_way_center(xg_string /* unused */, const QXmlStreamAttributes* attrv);
- void osm_way_end(xg_string /* unused */, const QXmlStreamAttributes* /* unused */);
+ void osm_node_end(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
+ void osm_node(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_node_tag(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_way(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_way_nd(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_way_tag(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_way_center(const QString& /* unused */, const QXmlStreamAttributes* attrv);
+ void osm_way_end(const QString& /* unused */, const QXmlStreamAttributes* /* unused */);
void osm_init_icons();
void osm_write_tag(const QString& key, const QString& value) const;
void osm_disp_feature(const Waypoint* waypoint) const;
route_head* rte{};
Waypoint* wpt{};
- QList<xg_functor_map_entry<OsmFormat>> osm_map = {
- {&OsmFormat::osm_node, cb_start, "/osm/node"},
- {&OsmFormat::osm_node_tag, cb_start, "/osm/node/tag"},
- {&OsmFormat::osm_node_end, cb_end, "/osm/node"},
- {&OsmFormat::osm_way, cb_start, "/osm/way"},
- {&OsmFormat::osm_way_nd, cb_start, "/osm/way/nd"},
- {&OsmFormat::osm_way_tag, cb_start, "/osm/way/tag"},
- {&OsmFormat::osm_way_center, cb_start, "/osm/way/center"},
- {&OsmFormat::osm_way_end, cb_end, "/osm/way"}
+ QList<XmlGenericReader::xg_fmt_map_entry<OsmFormat>> osm_map {
+ {&OsmFormat::osm_node, xg_cb_type::cb_start, "/osm/node"},
+ {&OsmFormat::osm_node_tag, xg_cb_type::cb_start, "/osm/node/tag"},
+ {&OsmFormat::osm_node_end, xg_cb_type::cb_end, "/osm/node"},
+ {&OsmFormat::osm_way, xg_cb_type::cb_start, "/osm/way"},
+ {&OsmFormat::osm_way_nd, xg_cb_type::cb_start, "/osm/way/nd"},
+ {&OsmFormat::osm_way_tag, xg_cb_type::cb_start, "/osm/way/tag"},
+ {&OsmFormat::osm_way_center, xg_cb_type::cb_start, "/osm/way/center"},
+ {&OsmFormat::osm_way_end, xg_cb_type::cb_end, "/osm/way"}
};
+ XmlGenericReader* xml_reader{nullptr};
};
#endif // OSM_H_INCLUDED_
*/
-#include <QByteArray> // for QByteArray
-#include <QHash> // for QHash
-#include <QIODevice> // for QIODevice, QIODevice::ReadOnly
-#include <QLatin1Char> // for QLatin1Char
-#include <QList>
-#include <QStringView> // for QStringView
-#include <QTextCodec> // for QTextCodec
-#include <QXmlStreamAttributes> // for QXmlStreamAttributes
-#include <QXmlStreamReader> // for QXmlStreamReader, QXmlStreamReader::Characters, QXmlStreamReader::EndElement, QXmlStreamReader::IncludeChildElements, QXmlStreamReader::StartDocument, QXmlStreamReader::StartElement
-#include <QtGlobal> // for qPrintable
-
-#include "defs.h"
#include "xmlgeneric.h"
-#include "src/core/file.h" // for File
+#include <utility> // for as_const
-enum xg_shortcut {
- xg_shortcut_none = 0,
- xg_shortcut_skip,
- xg_shortcut_ignore
-};
+#include <QByteArray> // for QByteArray
+#include <QHash> // for QHash
+#include <QIODevice> // for QIODevice
+#include <QLatin1Char> // for QLatin1Char
+#include <QStringView> // for QStringView
+#include <QTextCodec> // for QTextCodec
+#include <QXmlStreamAttributes> // for QXmlStreamAttributes, QXmlStreamReader::Characters, QXmlStreamReader::EndElement, QXmlStreamReader::IncludeChildElements, QXmlStreamReader::StartDocument, QXmlStreamReader::StartElement
+#include <QXmlStreamReader> // for QXmlStreamReader
+//#include <QtCore> // for QHash, QIODeviceBase::ReadOnly
+#include <QtGlobal> // for qPrintable
-static const QList<xg_tag_map_entry>* xg_tag_tbl;
-static bool dynamic_tag_tbl;
-static QHash<QString, xg_shortcut>* xg_shortcut_taglist;
+#include "defs.h" // for fatal
+#include "src/core/file.h" // for File
-static QString rd_fname;
-static QByteArray reader_data;
-static const char* xg_encoding;
-static QTextCodec* utf8_codec = QTextCodec::codecForName("UTF-8");
-static QTextCodec* codec = utf8_codec; // Qt has no vanilla ASCII encoding =(
#define MYNAME "XML Reader"
* xml strains and insulates us from a lot of the grubbiness of expat.
*/
-static XgCallbackBase*
-xml_tbl_lookup(const QString& tag, xg_cb_type cb_type)
+XmlGenericReader::XgCallbackBase*
+XmlGenericReader::xml_tbl_lookup(const QString& tag, xg_cb_type cb_type)
{
- for (const auto& tm : *xg_tag_tbl) {
+ for (const auto& tm : std::as_const(xg_tag_tbl)) {
if (cb_type == tm.cb_type) {
QRegularExpressionMatch match = tm.tag_re.match(tag);
if (match.hasMatch()) {
- return tm.tag_cb;
+ return tm.tag_cb.get();
}
}
}
return nullptr;
}
-static void
-xml_common_init(const QString& fname, const char* encoding,
- const char* const* ignorelist, const char* const* skiplist)
+void
+XmlGenericReader::xml_common_init(const QString& fname, const char* encoding,
+ const char* const* ignorelist, const char* const* skiplist)
{
rd_fname = fname;
- xg_encoding = encoding;
- if (encoding) {
- QTextCodec* tcodec = QTextCodec::codecForName(encoding);
- if (tcodec) {
- codec = tcodec;
+ if (encoding != nullptr) {
+ codec = QTextCodec::codecForName(encoding);
+ if (codec == nullptr) {
+ fatal(MYNAME " : codec \"%s\" is not available.\n", encoding);
}
+ } else {
+ codec = QTextCodec::codecForName("UTF-8");
}
- xg_shortcut_taglist = new QHash<QString, xg_shortcut>;
+ xg_shortcut_taglist.clear();
if (ignorelist != nullptr) {
for (; ignorelist && *ignorelist; ++ignorelist) {
- xg_shortcut_taglist->insert(QString::fromUtf8(*ignorelist), xg_shortcut_ignore);
+ xg_shortcut_taglist.insert(QString::fromUtf8(*ignorelist), xg_shortcut::sc_ignore);
}
}
if (skiplist != nullptr) {
for (; skiplist && *skiplist; ++skiplist) {
- xg_shortcut_taglist->insert(QString::fromUtf8(*skiplist), xg_shortcut_skip);
- }
- }
-}
-
-void
-xml_init(const QString& fname, const QList<xg_tag_map_entry>* tbl, const char* encoding,
- const char* const* ignorelist, const char* const* skiplist, bool dynamic_tbl)
-{
- xg_tag_tbl = tbl;
- dynamic_tag_tbl = dynamic_tbl;
-
- xml_common_init(fname, encoding, ignorelist, skiplist);
-}
-
-void
-xml_init(const QString& fname, const QList<xg_tag_mapping>& tbl, const char* encoding,
- const char* const* ignorelist, const char* const* skiplist)
-{
- auto* tag_tbl = new QList<xg_tag_map_entry>;
- dynamic_tag_tbl = true;
- for (const auto& tm : tbl) {
- auto* cb = new XgFunctionPtrCallback(tm.tag_cb);
- QRegularExpression re(QRegularExpression::anchoredPattern(tm.tag_pattern));
- assert(re.isValid());
- tag_tbl->append({cb, tm.cb_type, re});
- }
- xg_tag_tbl = tag_tbl;
-
- xml_common_init(fname, encoding, ignorelist, skiplist);
-}
-
-void
-xml_deinit()
-{
- if (dynamic_tag_tbl) {
- for (const auto& tm : *xg_tag_tbl) {
- delete tm.tag_cb;
+ xg_shortcut_taglist.insert(QString::fromUtf8(*skiplist), xg_shortcut::sc_skip);
}
- delete xg_tag_tbl;
}
- xg_tag_tbl = nullptr;
-
- reader_data.clear();
- rd_fname.clear();
-
- xg_encoding = nullptr;
- codec = utf8_codec;
-
- delete xg_shortcut_taglist;
- xg_shortcut_taglist = nullptr;
}
-static xg_shortcut
-xml_shortcut(QStringView name)
+XmlGenericReader::xg_shortcut
+XmlGenericReader::xml_shortcut(QStringView name)
{
QString key = name.toString();
- if (xg_shortcut_taglist->contains(key)) {
- return xg_shortcut_taglist->value(key);
+ if (xg_shortcut_taglist.contains(key)) {
+ return xg_shortcut_taglist.value(key);
}
- return xg_shortcut_none;
+ return xg_shortcut::sc_none;
}
-static void
-xml_run_parser(QXmlStreamReader& reader)
+void
+XmlGenericReader::xml_run_parser(QXmlStreamReader& reader)
{
XgCallbackBase* cb;
QString current_tag;
case QXmlStreamReader::StartElement:
switch (xml_shortcut(reader.name())) {
- case xg_shortcut_skip:
+ case xg_shortcut::sc_skip:
reader.skipCurrentElement();
goto readnext;
- case xg_shortcut_ignore:
+ case xg_shortcut::sc_ignore:
goto readnext;
default:
break;
current_tag.append(QLatin1Char('/'));
current_tag.append(reader.qualifiedName());
- cb = xml_tbl_lookup(current_tag, cb_start);
+ cb = xml_tbl_lookup(current_tag, xg_cb_type::cb_start);
if (cb) {
const QXmlStreamAttributes attrs = reader.attributes();
(*cb)(nullptr, &attrs);
}
- cb = xml_tbl_lookup(current_tag, cb_cdata);
+ cb = xml_tbl_lookup(current_tag, xg_cb_type::cb_cdata);
if (cb) {
QString c = reader.readElementText(QXmlStreamReader::IncludeChildElements);
// readElementText advances the tokenType to QXmlStreamReader::EndElement,
break;
case QXmlStreamReader::EndElement:
- if (xml_shortcut(reader.name()) == xg_shortcut_skip) {
+ if (xml_shortcut(reader.name()) == xg_shortcut::sc_skip) {
goto readnext;
}
- cb = xml_tbl_lookup(current_tag, cb_end);
+ cb = xml_tbl_lookup(current_tag, xg_cb_type::cb_end);
if (cb) {
(*cb)(reader.name().toString(), nullptr);
}
}
}
-void xml_read()
+void XmlGenericReader::xml_read()
{
gpsbabel::File file(rd_fname);
xml_run_parser(reader);
if (reader.hasError()) {
- fatal(MYNAME ":Read error: %s (%s, line %lld, col %lld)\n",
+ fatal(MYNAME " :Read error: %s (%s, line %lld, col %lld)\n",
qPrintable(reader.errorString()),
qPrintable(file.fileName()),
reader.lineNumber(),
// Chucks some bytes into the global QByteArray buffer and waits for
// xml_readstring() to parse.
-void xml_readprefixstring(const char* str)
+void XmlGenericReader::xml_readprefixstring(const char* str)
{
reader_data.append(str);
}
// Parses a bytestream as if it were a file. Looks for an <?xml encoding= to
// determine file encoding, falls back to UTF-8 if unspecified.
-void xml_readstring(const char* str)
+void XmlGenericReader::xml_readstring(const char* str)
{
reader_data.append(str);
xml_run_parser(reader);
if (reader.hasError()) {
- fatal(MYNAME ":Read error: %s (%s, line %lld, col %lld)\n",
+ fatal(MYNAME " :Read error: %s (%s, line %lld, col %lld)\n",
qPrintable(reader.errorString()),
"unknown",
reader.lineNumber(),
// This is quite different from xml_readstring(). It doesn't have to interpret
// encoding because the source is already Qt's internal UTF-16.
-void xml_readunicode(const QString& str)
+void XmlGenericReader::xml_readunicode(const QString& str)
{
QXmlStreamReader reader(str);
#define XMLGENERIC_H_INCLUDED_
#include <cassert> // for assert
+#include <memory> // for make_shared, shared_ptr
+#include <QByteArray> // for QByteArray
+#include <QHash> // for QHash
#include <QList> // for QList
#include <QRegularExpression> // for QRegularExpression
#include <QString> // for QString
+#include <QStringView> // for QStringView
+#include <QTextCodec> // for QTextCodec
#include <QXmlStreamAttributes> // for QXmlStreamAttributes
+#include <QXmlStreamReader> // for QXmlStreamReader
-// Maybe the XmlGeneric string callback really shouldn't have a type
-// of its own; this was a crutch during the move from char* to QString.
-// It's "just" a search and replace to make it go away, but it might
-// be convenient to overload some day.
-using xg_string = const QString&;
-
-enum xg_cb_type {
- cb_start = 1,
+enum class xg_cb_type {
+ cb_unknown = 0,
+ cb_start,
cb_cdata,
cb_end,
};
-class XgCallbackBase
-{
-public:
- XgCallbackBase() = default;
- virtual ~XgCallbackBase() = default;
- XgCallbackBase(const XgCallbackBase&) = delete;
- XgCallbackBase& operator=(const XgCallbackBase&) = delete;
- XgCallbackBase(XgCallbackBase&&) = delete;
- XgCallbackBase& operator=(XgCallbackBase&&) = delete;
-
- virtual void operator()(xg_string string, const QXmlStreamAttributes* attrs) const = 0;
-};
-
-template<class XgFormat>
-class XgFunctor : public XgCallbackBase
+/*
+ * xml_init will build and own a table of XgFunctor and/or
+ * XgFunctionPtrCallback entries from a list
+ * of non-static member functions and/or function pointers.
+ *
+ * QList<XmlGenericReader::xg_fmt_map_entry<SomeFormat>> some_map = {
+ * {&SomeFormat::memberfn, cb_start, "/Placemark"},
+ * {staticfn, cb_cdata, "/Placemark/coord"},
+ * };
+ *
+ * The this pointer from the Format instance must be passed if any
+ * of the callbacks are member functions, otherwise nullptr can be passed
+ * as this.
+ *
+ * xml_init(fname, this, some_map, encoding, ignorelist, skiplist);
+ *
+ */
+class XmlGenericReader
{
public:
- using XgCb = void (XgFormat::*)(xg_string, const QXmlStreamAttributes*);
- XgFunctor(XgFormat* obj, XgCb cb) : that_(obj), cb_(cb) {}
- void operator()(xg_string string, const QXmlStreamAttributes* attrs) const override
+ /* Types */
+
+ // formats pass a list containing member function pointers and/or function pointers.
+ template<class MyFormat>
+ struct xg_fmt_map_entry {
+ // Constructor from a Member Function Pointer
+ using XgMfpCb = void (MyFormat::*)(const QString&, const QXmlStreamAttributes*);
+ xg_fmt_map_entry(XgMfpCb mfp, xg_cb_type ty, const char* tp) : tag_mfp_cb(mfp), cb_type(ty), tag_pattern(tp) {}
+ // Constructor from a Function Pointer.
+ using XgFpCb = void (const QString&, const QXmlStreamAttributes*);
+ xg_fmt_map_entry(XgFpCb fp, xg_cb_type ty, const char* tp) : tag_fp_cb(fp), cb_type(ty), tag_pattern(tp) {}
+
+ /* Data Members */
+
+ XgMfpCb tag_mfp_cb{nullptr};
+ XgFpCb* tag_fp_cb{nullptr};
+ xg_cb_type cb_type{xg_cb_type::cb_unknown};
+ const char* tag_pattern{nullptr};
+ };
+
+ /* Member Functions */
+
+ template<class MyFormat>
+ void xml_init(const QString& fname, MyFormat* instance, const QList<xg_fmt_map_entry<MyFormat>>& tbl,
+ const char* encoding = nullptr,
+ const char* const* ignorelist = nullptr,
+ const char* const* skiplist = nullptr)
{
- (that_->*cb_)(string, attrs);
+ build_xg_tag_map(instance, tbl);
+
+ xml_common_init(fname, encoding, ignorelist, skiplist);
}
+ void xml_read();
+ void xml_readstring(const char* str);
+ void xml_readprefixstring(const char* str);
+ void xml_readunicode(const QString& str);
+
private:
- XgFormat* that_;
- XgCb cb_;
-};
+ /* Types */
-class XgFunctionPtrCallback : public XgCallbackBase
-{
-public:
- using XgCb = void (xg_string, const QXmlStreamAttributes*);
- explicit XgFunctionPtrCallback(XgCb cb) : cb_(cb) {}
- void operator()(xg_string string, const QXmlStreamAttributes* attrs) const override
+ class XgCallbackBase
+ {
+ public:
+ XgCallbackBase() = default;
+ virtual ~XgCallbackBase() = default;
+ XgCallbackBase(const XgCallbackBase&) = delete;
+ XgCallbackBase& operator=(const XgCallbackBase&) = delete;
+ XgCallbackBase(XgCallbackBase&&) = delete;
+ XgCallbackBase& operator=(XgCallbackBase&&) = delete;
+
+ virtual void operator()(const QString& string, const QXmlStreamAttributes* attrs) const = 0;
+ };
+
+ template<class XgFormat>
+ class XgFunctor : public XgCallbackBase
{
- (*cb_)(string, attrs);
+ public:
+ using XgCb = void (XgFormat::*)(const QString&, const QXmlStreamAttributes*);
+ XgFunctor(XgFormat* obj, XgCb cb) : that_(obj), cb_(cb) {}
+ void operator()(const QString& string, const QXmlStreamAttributes* attrs) const override
+ {
+ (that_->*cb_)(string, attrs);
+ }
+
+ private:
+ XgFormat* that_;
+ XgCb cb_;
+ };
+
+ class XgFunctionPtrCallback : public XgCallbackBase
+ {
+ public:
+ using XgCb = void (const QString&, const QXmlStreamAttributes*);
+ explicit XgFunctionPtrCallback(XgCb cb) : cb_(cb) {}
+ void operator()(const QString& string, const QXmlStreamAttributes* attrs) const override
+ {
+ (*cb_)(string, attrs);
+ }
+
+ private:
+ XgCb* cb_;
+ };
+
+ // xml processing uses a list of xg_tag_map_entries.
+ struct xg_tag_map_entry {
+ std::shared_ptr<XgCallbackBase> tag_cb{nullptr};
+ xg_cb_type cb_type{xg_cb_type::cb_unknown};
+ QRegularExpression tag_re;
+ };
+
+ enum class xg_shortcut {
+ sc_none = 0,
+ sc_skip,
+ sc_ignore
+ };
+
+ /* Member Functions */
+
+ XgCallbackBase* xml_tbl_lookup(const QString& tag, xg_cb_type cb_type);
+ void xml_common_init(const QString& fname, const char* encoding,
+ const char* const* ignorelist, const char* const* skiplist);
+ xg_shortcut xml_shortcut(QStringView name);
+ void xml_run_parser(QXmlStreamReader& reader);
+
+ // translate xg_fmt_map_entries to xg_tag_map_entries.
+ template<class MyFormat>
+ void build_xg_tag_map(MyFormat* instance, const QList<xg_fmt_map_entry<MyFormat>>& map)
+ {
+ xg_tag_tbl.clear();
+ for (const auto& entry : map) {
+ xg_tag_map_entry tme;
+ if (entry.tag_mfp_cb != nullptr) {
+ tme.tag_cb = std::make_shared<XgFunctor<MyFormat>>(instance, entry.tag_mfp_cb);
+ } else {
+ tme.tag_cb = std::make_shared<XgFunctionPtrCallback>(entry.tag_fp_cb);
+ }
+ QRegularExpression re(QRegularExpression::anchoredPattern(entry.tag_pattern));
+ assert(re.isValid());
+ tme.cb_type = entry.cb_type;
+ tme.tag_re = re;
+ xg_tag_tbl.append(tme);
+ }
}
-private:
- XgCb* cb_;
-};
+ /* Data Members */
-// xml processing uses a QList<xg_tag_map_entry>.
-// You may generated this yourself. See method 1 below.
-// Or it may be generated for you using one of the subsequent
-// methods.
-struct xg_tag_map_entry {
- XgCallbackBase* tag_cb;
- xg_cb_type cb_type;
- QRegularExpression tag_re;
-};
+ QList<xg_tag_map_entry> xg_tag_tbl;
+ QHash<QString, xg_shortcut> xg_shortcut_taglist;
-// Table generation from an array containing function pointers.
-// The above table can be generated by xml_init. See method 2 below.
-// This is how things done historically before the Format class was
-// introduced.
-using xg_callback = void (xg_string, const QXmlStreamAttributes*);
-struct xg_tag_mapping {
- xg_callback* tag_cb;
- xg_cb_type cb_type;
- const char* tag_pattern;
-};
+ QString rd_fname;
+ QByteArray reader_data;
+ QTextCodec* codec{nullptr}; // Qt has no vanilla ASCII encoding =(
-// Table generation from a list containing member function pointers.
-// The above table can be generated by xml_init. See method 3 below.
-template<class MyFormat>
-struct xg_functor_map_entry {
- using XgCb = void (MyFormat::*)(xg_string, const QXmlStreamAttributes*);
- XgCb tag_cb;
- xg_cb_type cb_type;
- const char* tag_pattern;
};
-template<class MyFormat, typename my_functor_map_entry>
-QList<xg_tag_map_entry>* build_xg_tag_map(MyFormat* instance, const QList<my_functor_map_entry>& map)
-{
- auto* tag_tbl = new QList<xg_tag_map_entry>;
- for (const auto& entry : map) {
- auto* tag_cb = new XgFunctor<MyFormat>(instance, entry.tag_cb);
- QRegularExpression re(QRegularExpression::anchoredPattern(entry.tag_pattern));
- assert(re.isValid());
- tag_tbl->append({tag_cb, entry.cb_type, re});
- }
- return tag_tbl;
-}
-
-/*
- * There are multiple ways to initialize with xml_init.
- *
- * 1. Build your own QList<xg_tag_map_entry>, and pass it.
- * You own the table, you must do any required clean up.
- * Your callbacks may be a mix of function pointers wrapped in XgFunctors
- * and non-static member functions wrapped in XgFunctionPtrCallbacks.
- * and XgFunctionPtrCallback(for static member functions or global functions) entries.
- * xml_init(fname, tbl, encoding, ignorelist, skiplist, false);
- * You must set the dynamic_tbl parameter to false so xml_deninit doesn't
- * attempt to free the table resources when xml_deinit is called.
- *
- * 2. Have xml_init build and own a table of XgFunctionPtrCallback entries
- * from an list of function pointers, i.e. a QList of xg_tag_mapping elements.
- * This only works when all callbacks are function pointers.
- * xml_init(fname, tbl, encoding, ignorelist, skiplist);
- * Generated table entries will automatically be freed.
- *
- * 3. Have xml_init build and own a table of XgFunctor entries from a list
- * of non-static member functions, i.e. a QList<my_functor_map_entry>.
- * This only works when all callbacks are non-static member functions.
- * xml_init(fname, build_xg_tag_map(instance, map), encoding, ignorelist, skiplist, true);
- * You must set the dynamic_tbl parameter to true to free the generated table
- * resources when xml_deinit is called.
- *
- */
-void xml_init(const QString& fname, const QList<xg_tag_map_entry>* tbl, const char* encoding,
- const char* const* ignorelist = nullptr,
- const char* const* skiplist = nullptr, bool dynamic_tbl = false);
-void xml_init(const QString& fname, const QList<xg_tag_mapping>& tbl,const char* encoding,
- const char* const* ignorelist = nullptr,
- const char* const* skiplist = nullptr);
-void xml_read();
-void xml_readstring(const char* str);
-void xml_readprefixstring(const char* str);
-void xml_readunicode(const QString& str);
-void xml_deinit();
-
#endif // XMLGENERIC_H_INCLUDED_